package com.hulk.rpc.loadbalance.impl;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.hulk.rpc.loadbalance.LoadBalance;
import com.hulk.rpc.loadbalance.Weightable;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xuxukang
 * @date 2019-03-27 22:49
 */
public class WeightRoundRobinBalance<T extends Weightable> extends LoadBalance<T> {

  private static final AtomicInteger tryCounter = new AtomicInteger(0);

  // 基于权重的资源列表（权重为10，就有10条相同记录）
  private List<T> weightableResources = Lists.newArrayList();

  @Override
  public T select() {
    if (CollUtil.isEmpty(weightableResources)) {
      copyWeightableResources();
    }

    return weightableResources.get(tryCounter.getAndIncrement() % weightableResources.size());
  }

  @Override
  public void clean() {
    weightableResources.clear();
    copyWeightableResources();
    tryCounter.set(0);
  }

  private void copyWeightableResources() {
    resources.parallelStream()
            .sorted((o1, o2) -> Integer.compare(o2.weight(), o1.weight()))
            .forEachOrdered(resource -> {
              for (int i = 0; i < resource.weight(); i++) {
                weightableResources.add(resource);
              }
            });
  }
}
